/*
 * Copyright Iain Sproat, 2008
 * 
 *
 */

using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using Rhino.Mocks;
using log4net;
using log4net.Config;

using FreeBase;
using FreeBase.Domain;
using FreeBase.Linq;

namespace FreeBase_Test.Linq
{
	[TestFixture]
	public class ExamplesFromCheatSheet
	{
		private readonly ILog logger = LogManager.GetLogger(typeof(TestFreebaseExpressionVisitor));
		
		//TODO change fluent expressions to Linq expressions
		//create sample data to be returned by mock QueryProvider
		MockRepository mocks = null;
		IQueryProvider prov = null;
		IFreebaseClient client = null;
		
		[SetUp]
		public void SetUp()
		{
			//setup logging
			BasicConfigurator.Configure();
			
			//mocks
			mocks = new MockRepository();
			client = mocks.DynamicMock<IFreebaseClient>( );
			prov = new FreebaseQueryProvider( client );
		}
		
		[Test]
		public void RunPoliceTrackExample()
		{
			
			/*FBQuery ThePolice_TrackNames_BeginningWith_Message =
				Freebase.Query
				.Where().Name.Is("The Police")
				.Where().Type.Is("/music/artist")
				.Expect.Many("track").Which.Meets(
					Freebase.Query
					.Show.OneRecordFor.AllProperties
					.Where().Name.StartsWith("Message")
					.LimitNumberOfResults.To(1)
				);*/
			string expected = "{\"query\":" +
				"[{\"name\":\"The Police\"," +
				"\"type\":\"/music/artist\"," +
				"\"track\":[{" +
				"\"*\":null," +
				"\"name~=\":\"^Message\"," +
				"\"limit\":1" +
				"}]}]}";
			string returned = "{" +
				"\"status\":\"200 OK\"," +
				"\"code\":\"/api/status/ok\"," +
				"\"result\":[{" +
				"\"track\":[{" +
				"\"name\":\"Message In a Bottle\"" +
				"}]" +
				"}]," +
				"\"transaction_id\":\"cache:cache01.p01.sjc1:8101...\"" +
				"}";
			
			using( mocks.Record( ) )
			{
				Expect.Call( client.Read( expected ) )
					.Return( returned )
					.Repeat.Once()
					.IgnoreArguments(); //HACK until we improve the expression visitor
			}
			
			using( mocks.Playback( ) )
			{
				var queryable = new Query<Artist>( prov );
				IQueryable<Artist> query =
					from artist in queryable
					where artist.Name == "The Police" &&
					artist.Type == ("/music/artist")
					select artist;
				
				Assert.IsNotNull( query );
				
				IEnumerator<Artist> enumerator = query.GetEnumerator();
				Assert.IsNotNull( enumerator );
				
				Artist currentArtist = null;
				while( enumerator.MoveNext() )
				{
					currentArtist = (Artist)enumerator.Current;
					Assert.IsNotNull( currentArtist );
					logger.Debug( "We have " + currentArtist.ToString() );
				}
				
			}
			
		}
		
		/*[Test]
		public void CanANDCriteria()
		{
			
			FBQuery ThePolice_TrackNames_BeginningWithMessage_And_ContainingBottle =
				Freebase.Query
				.Where().Name.Is("The Police")
				.Where().Type.Is("/music/artist")
				.Expect.Many("track").Which.Meets(
					Freebase.Query
					.Show.OneRecordFor.AllProperties
					.Where().Name.StartsWith("Message")
					.Where().Name.Contains("Bottle")
					.LimitNumberOfResults.To(1)
				);
			
			Assert.IsNotNull( ThePolice_TrackNames_BeginningWithMessage_And_ContainingBottle );
			
			IMQLConverter SUT = new FluentMQLConverter();
			string ret = SUT.FluentToMQL( ThePolice_TrackNames_BeginningWithMessage_And_ContainingBottle );
			string expected = "{\"query\":" +
				"[{\"name\":\"The Police\"," +
				"\"type\":\"/music/artist\"," +
				"\"track\":[{" +
				"\"*\":null," +
				"\"criteria0:name~=\":\"^Message\"," +
				"\"criteria1:name~=\":\"Bottle\"," +
				"\"limit\":1" +
				"}]}]}";
			Console.WriteLine( "And Test => " + ret );
			Assert.AreEqual( expected, ret);
		}
		
		[Test]
		public void CanOrCriteria()
		{
			
			FBQuery ThePolice_TrackNames_WhichAre_MessageInABottle_Or_EveryBreathYouTake =
				Freebase.Query
				.Where().Name.Is("The Police")
				.Where().Type.Is("/music/artist")
				.Expect.Many("track").Which.Meets(
					Freebase.Query
					.Show.OneRecordFor.AllProperties
					.Where().Name.Is("Message In A Bottle",
					                 "Every Breath You Take") //This is an OR statement
					.LimitNumberOfResults.To(2)
				);
			
			Assert.IsNotNull( ThePolice_TrackNames_WhichAre_MessageInABottle_Or_EveryBreathYouTake );
			
			IMQLConverter SUT = new FluentMQLConverter();
			string ret = SUT.FluentToMQL( ThePolice_TrackNames_WhichAre_MessageInABottle_Or_EveryBreathYouTake );
			string expected = "{\"query\":" +
				"[{\"name\":\"The Police\"," +
				"\"type\":\"/music/artist\"," +
				"\"track\":[{" +
				"\"*\":null," +
				"\"name|=\":[\"Message In A Bottle\",\"Every Breath You Take\"]," +
				"\"limit\":2" +
				"}]}]}";
			Console.WriteLine( "OR test => " + ret );
			Assert.AreEqual( expected, ret);
		}*/
	}
}
